<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>隐式丢失this的5种情况</title>
</head>

<body>

</body>
<script>
  // 隐式丢失就是指被隐式绑定的函数丢失了绑定对象，从而默认绑定到了window
  // 这种情况非常容易出错且又非常常见
  // 1、隐式丢失，函数别名
  var a = 0;
  function foo() {
    console.log(this.a);
  }
  var obj = {
    a: 1,
    foo: foo
  }
  // 把obj.foo()赋值给变量bar，造成隐式丢失的情况，因为只是把obj.foo赋值给了bar变量，
  // 而bar与obj毫无关系
  var bar = obj.foo;
  bar();

  // 2、参数传递
  var a = 0;
  function foo() {
    console.log(this.a);
  }
  function bar(fn) {
    fn();
  }
  var obj = {
    a: 1,
    foo: foo
  }
  // 把obj.foo当作参数传递到bar函数中，有隐式的函数赋值 fn=obj.foo,只是把foo函数赋值给了fn,而fn函数与obj对象毫无关系，所以当前foo函数内部的this指向了window
  bar(obj.foo);

  // 3、内置函数，setTimeout()和setInterval()第一个参数的回调函数中的this，默认指向了window，跟第2种情况是类似的
  var a = 0;
  function foo() {
    console.log(this.a);
  }
  var obj = {
    a: 1,
    foo: foo
  }

  setTimeout(obj.foo, 1000);

  // 4、间接调用
  var a = 0;
  function foo() {
    console.log(this.a);
  }
  var obj = {
    a: 1,
    foo: foo
  }
  var p = { a: 2 };
  // 隐式绑定，函数当作对象的方法来使用，内部的this指向了obj
  obj.foo();  //1
  // 将obj.foo函数对象赋值给了p.foo()函数，然后立即执行，相当于仅仅是foo()函数的立即调用，内部的this默认指向了window
  (p.foo = obj.foo)();  //0
  p.foo = obj.foo
  p.foo();  //2

  // 5、其他情况，指向了window的特殊情况
  var a = 0;
  function foo() {
    console.log(this.a);
  }
  var obj = {
    a: 1,
    foo: foo
  }
  (obj.foo = obj.foo)();  //0
  (false || obj.foo)(); //0
  (1,obj.foo)();  //0

















</script>

</html>